package oa.dao.base.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import oa.dao.base.BaseDao;
import oa.domain.page.PageBean;
import oa.util.HQLHelper;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class BaseDaoImpl<E> implements BaseDao<E>{

	@Resource
	private SessionFactory sessionFactory;
	
	@Resource(name="hibernateTemplate")	
	public HibernateTemplate hibernateTemplate;
	
	private Class classt;
	private ClassMetadata classMetadata;
	/**
	 * 当调用完构造函数之后，立刻执行该方法
	 */
	@PostConstruct
	public void init()
	{
		classMetadata = this.hibernateTemplate.getSessionFactory().getClassMetadata(this.classt);
	}
	
	public BaseDaoImpl()
	{
		ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
		this.classt = (Class)type.getActualTypeArguments()[0];
	}
	
	@Override
	public Collection<E> getAllEntry() {
		// TODO Auto-generated method stub
		return (Collection<E>) this.hibernateTemplate.find("from "+this.classt.getName());
	}

	@Override
	public void saveEntity(E e) {
		// TODO Auto-generated method stub
		this.hibernateTemplate.save(e);
	}

	@Override
	public E getEntryById(Serializable id) {
		// TODO Auto-generated method stub
	  return (E) this.hibernateTemplate.find("from " + this.classt.getName() +
				                " where " + classMetadata.getIdentifierPropertyName() +"="+ id).get(0);
		//在代码的最后需要加上.get(0)否则会提示类型转换错误，不能把ArrayList转换成实体类
	}

	@Override
	public void updateEntry(E e) {
		// TODO Auto-generated method stub
	      	this.hibernateTemplate.update(e);
	}

	@Override
	public void deleteEntry(Serializable id) {
		// TODO Auto-generated method stub
		E e = this.getEntryById(id);
		this.hibernateTemplate.delete(e);
	}

	@Override
	public Set<E> getEntryByIds(Serializable[] ids) {
		// TODO Auto-generated method stub
		/**
		 * 1、如果数组只有一个元素
		 * 2、如果数组中有两个或者两个以上的元素
		 *    from Person where pid in(1,2,3,4)
		 */
		
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("from " + this.classt.getName());
		stringBuffer.append(" where  " + this.classMetadata.getIdentifierPropertyName());
		stringBuffer.append(" in (");
		for(int i=0;i < ids.length ; i++)
		{
			if(i == ids.length-1)
			{
				stringBuffer.append(ids[i]);
			}
			else
			{
				stringBuffer.append(ids[i]+ ",");
			}
		}
		stringBuffer.append(")");
		List<E> list = (List<E>) this.hibernateTemplate.find(stringBuffer.toString());
		return new HashSet<E>(list);
		
	}

	@Override
	public Set<E> getEntryByIds(String checkedStr) {
		// TODO Auto-generated method stub
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("from "+ this.classt.getName());
		stringBuffer.append(" where " + this.classMetadata.getIdentifierPropertyName());
		stringBuffer.append(" in (");
		stringBuffer.append(checkedStr);
		stringBuffer.append(")");
		List<E> list = (List<E>)this.hibernateTemplate.find(stringBuffer.toString());	
		return new HashSet<E>(list);
	}

	/**
	 * 根据条件查找复合条件的对象
	 */
	@Override
	public E getEntryByCondition(final String hql, final String... objects) {
		// TODO Auto-generated method stub
		
		return this.hibernateTemplate.execute(new HibernateCallback<E>() {

			@Override
			public E doInHibernate(Session sesison) throws HibernateException,
					SQLException {
				Query query = sesison.createQuery(hql);
				int index = 0;
				for(String s:objects){
					query.setParameter(index, s);
					index++;
				}
				return (E) query.uniqueResult();
			}
		});
	}

	@Override
	public PageBean getPageBean(HQLHelper hh, int currentPage) {
		// TODO Auto-generated method stub
		int pageSize = getPageSize();
		int firstResult = (currentPage - 1) * pageSize;
		
		String  listHQL = hh.getListHQL();
		String countHQL = hh.getCountHQL();
		List<Object> args = hh.getArgs();
		
		Query query = sessionFactory.getCurrentSession().createQuery(listHQL);
		if(args != null && args.size() > 0)
		{
			int index = 0;
			for(Object a : args)
			{
				query.setParameter(index, a);
				index++;
			}
		}
		query.setFirstResult(firstResult);
		query.setMaxResults(pageSize);
		List recordList = query.list();
		
		query = sessionFactory.getCurrentSession().createQuery(countHQL);	
		if(args != null && args.size() > 0){
			int index = 0;
			for(Object o : args){
				query.setParameter(index++, o);
			}
		}
		Long recordCount = (Long) query.uniqueResult();
		return new PageBean(currentPage, pageSize, recordCount.intValue(), recordList);
	}
	

	private int getPageSize()
	{
		int pagesize = 0;
		Properties prop = new Properties();
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("page.properties");
		try {
			prop.load(inputStream);
//			String str = (String) prop.get("pageSize");
			String str = prop.getProperty("pageSize");
			pagesize = Integer.parseInt(str);
		} catch (IOException e) {
			pagesize = 10;
			// TODO Auto-generated catch block
			throw new RuntimeException("读取配置文件出错!");
		}finally{
		    if(inputStream != null)
		    {
		    	try {
					inputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					throw new RuntimeException("流关闭错误!");
				}
		    }
		}
		return pagesize;
	}
}

